﻿using AutoFacPack;
using Models;
using PublicType;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace RepositoryService
{
    public class DbContext:IService
    {
        public DbContext()
        {
            DB = new SqlSugarClient(new ConnectionConfig()
            {
                /// <summary>
                /// 本地Sqlite数据库连接地址
                /// </summary>
                ConnectionString = "Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "\\customcode.s3db;Pooling=true;FailIfMissing=false",
                DbType = DbType.Sqlite,
                InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
                IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样我就不多解释了
                //自定义特性
                //ConfigureExternalServices = new ConfigureExternalServices()
                //{
                //    EntityService = (property, column) => {
                //        if (property.Name == "xxx")
                //        {//根据列名    
                //            column.IsIgnore = true;
                //        }
                //        var attributes = property.GetCustomAttributes(true);//get all attributes     
                //        if (attributes.Any(it => it is KeyAttribute))//根据自定义属性    
                //        {
                //            column.IsPrimarykey = true;
                //        }
                //    },
                //    EntityNameService = (type, entity) => {
                //        var attributes = type.GetCustomAttributes(true);
                //        if (attributes.Any(it => it is TableAttribute))
                //        {
                //            entity.DbTableName = (attributes.First(it => it is TableAttribute) as TableAttribute).Name;
                //        }
                //    }
                //}

            });
            //调式代码 用来打印SQL 
            DB.Aop.OnLogExecuting = (sql, pars) =>
            {

                Console.WriteLine(sql + "\r\n" +
                    DB.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
                Console.WriteLine();
            };
            DB.Aop.OnLogExecuted =(sql,pars)=> // SQL执行完事件
{

            };
            DB.Aop.OnLogExecuting =(sql,pars)=> // SQL执行前事件
{

            };
            DB.Aop.OnError =(exp)=> //执行SQL错误事件
{
                //exp.sql exp.parameters可以拿到参数和错误Sql             
            };
            //DB.Aop.OnExecutingChangeSql =(sql,pars)=> {
            //    // SQL执行前可以修改SQL
            //    返回新的KeyValuePair < string，SugarParameter[]>（sql，pars）;

            //    return 
            //};

        }
        public String[] getSqlSugarDbType() 
        {
            return Enum.GetNames(typeof(DbType));
        }
        //注意：不能写成静态的，不能写成静态的
        public SqlSugarClient DB;//用来处理事务多表查询和复杂的操作

        public void CreateClassFile(string directoryPath, string nameSpace ) 
        {
            this.DB.DbFirst.CreateClassFile(directoryPath, nameSpace);
        }
        public ReturnData<List<DbElementEntity>> GetTableInfoList()
        {
            try
            {
                List<DbElementEntity> dbElementEntities = new List<DbElementEntity>();
                List<DbTableInfo> tables = this.DB.DbMaintenance.GetTableInfoList();
                for (int i = 0; i < tables.Count; i++)
                {
                    DbElementEntity dbElementEntity = new DbElementEntity();
                    dbElementEntity.Name = tables[i].Name;
                    dbElementEntity.Description = tables[i].Description;
                    switch (tables[i].DbObjectType)
                    {
                        case DbObjectType.Table:
                            dbElementEntity.DbElementType = DbElementType.Table;
                            break;
                        case DbObjectType.View:
                            dbElementEntity.DbElementType = DbElementType.View;
                            break;
                        case DbObjectType.All:
                            dbElementEntity.DbElementType = DbElementType.None;
                            break;
                        default:
                            break;
                    }
                    dbElementEntities.Add(dbElementEntity);
                }
                return ReturnData<List<DbElementEntity>>.SuccessResult(dbElementEntities);
            }
            catch (Exception ex)
            {
                return ReturnData<List<DbElementEntity>>.FailResult(ex.Message);
            }
        }
        public ReturnData<List<DbTableFieldEntity>> GetColumnInfosByTableName(String tableName)
        {
            try
            {
                List<DbTableFieldEntity> DbColumnEntitys = new List<DbTableFieldEntity>();
                List<DbColumnInfo> Columns = this.DB.DbMaintenance.GetColumnInfosByTableName(tableName);
                for (int i = 0; i < Columns.Count; i++)
                {
                    DbTableFieldEntity DbColumnEntity = new DbTableFieldEntity();
                    DbColumnEntity.FieldDescription = Columns[i].ColumnDescription;
                    DbColumnEntity.DataType = Columns[i].DataType;
                    DbColumnEntity.DbFieldName = Columns[i].DbColumnName;
                    DbColumnEntity.DecimalDigits = Columns[i].DecimalDigits;
                    DbColumnEntity.DefaultValue = Columns[i].DefaultValue;
                    DbColumnEntity.IsIdentity = Columns[i].IsIdentity;
                    DbColumnEntity.IsNullable = Columns[i].IsNullable;
                    DbColumnEntity.IsPrimarykey = Columns[i].IsPrimarykey;
                    DbColumnEntity.Length = Columns[i].Length;
                    DbColumnEntity.PropertyName = Columns[i].PropertyName;

                    if (Columns[i].PropertyType!=null)
                    {
                        DbColumnEntity.PropertyType = Columns[i].PropertyType.FullName;
                    }                    
                    DbColumnEntity.Scale = Columns[i].Scale;
                    DbColumnEntity.TableId = Columns[i].TableId;
                    //DbColumnEntity.TableName = Columns[i].TableName;
                    if (Columns[i].Value!=null)
                    {
                        DbColumnEntity.Value = Columns[i].Value.ToString();
                    }
                   
                    DbColumnEntitys.Add(DbColumnEntity);
                }
                return ReturnData<List<DbTableFieldEntity>>.SuccessResult(DbColumnEntitys);
            }
            catch (Exception ex)
            {
                return ReturnData<List<DbTableFieldEntity>>.FailResult(ex.Message);
            }
        }
        public Dictionary<String, String> ToClassStringList()
        {
            return this.DB.DbFirst.ToClassStringList();
        }
    }
    public class DbContext<T>: DbContext where T:class,new ()
    {
        public SimpleClient<T> Storages { get { return new SimpleClient<T>(DB); } }//用来处理School表的常用操作

        public Boolean Insert(T t) 
        {
            return this.Storages.Insert(t);
        }
        public Boolean InsertRange(List<T> t)
        {
            return this.Storages.InsertRange(t);
        }
        public int InsertReturnIdentity(T t)
        {
            return this.Storages.InsertReturnIdentity(t);
        }

        public int DeleteById(dynamic id)
        {
            return this.Storages.DeleteById(id);
        }
        public T GetById(dynamic id)
        {
            return this.Storages.GetById(id);
        }
        public int Count(Expression<Func<T, bool>> whereExpression)
        {
            return this.Storages.Count(whereExpression);
        }

        public Boolean Delete(Expression<Func<T, bool>> whereExpression)
        {
            return this.Storages.Delete(whereExpression);
        }
        public Boolean Delete(T t)
        {
            return this.Storages.Delete(t);
        }

        public Boolean DeleteByIds(List<dynamic> ids)
        {
            return this.Storages.DeleteByIds(ids.ToArray());
        }

        public List<T> GetList()
        {
            return this.Storages.GetList();
        }
        public List<T> GetList(Expression<Func<T, bool>> whereExpression)
        {
            return this.Storages.GetList(whereExpression);
        }

        public List<T> GetPageList(Expression<Func<T, bool>> whereExpression,int pageIndex,int pageSize)
        {
            return this.Storages.GetPageList(whereExpression,new PageModel() { PageIndex = pageIndex , PageSize = pageSize });
        }

        public List<T> GetPageList(Expression<Func<T, bool>> whereExpression, int pageIndex, int pageSize, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return this.Storages.GetPageList(whereExpression, new PageModel() { PageIndex = pageIndex, PageSize = pageSize }, orderByExpression, orderByType);
        }
        public T GetSingle(Expression<Func<T, bool>> whereExpression)
        {
            return this.Storages.GetSingle(whereExpression);
        }
        public Boolean IsAny(Expression<Func<T, bool>> whereExpression)
        {
            return this.Storages.IsAny(whereExpression);
        }
        public Boolean Update(T t)
        {
            return this.Storages.Update(t);
        }

        public Boolean UpdateRange(List<T> t)
        {
            return this.Storages.UpdateRange(t);
        }


    }
}
